using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Windows.Forms;
namespace Circus.CodeEditor {
    public sealed partial class Painter {
        public Painter()
            : this(new Font(FontFamily.GenericMonospace, 30f)) { 
        }
        private Graphics graphics;
        private int oldMode = 1;
        private bool transFormed;
        private bool safeTransformed;
        private Win32.XFORM xForm;
        private Win32.XFORM safexForm;
        private int bufferSize = 0;
        private int[] buffer; 
        private bool opaque = false;
        private int lineSpace;


        public Color TextColor {
            get {
                return fromRGB(textColor);
            }
            set {
                textColor = toRGB(value);
            }
        }

        public Color ForeColor {
            get {
                return fromRGB(foreColor);
            }
            set {
                foreColor = toRGB(value);
            }
        }

        public Color BackColor {
            get {
                return fromRGB(backColor);
            }
            set {
                backColor = toRGB(value);
            }
        }

        public bool Opaque {
            get {
                return this.opaque;
            }
            set {
                if (this.opaque != value) {
                    this.opaque = value;
                    this.SelectOpaque(value);
                }
            }
        }

        public int FontWidth {
            get {
                return measureString(' ');
            }
        }

        public int FontHeight {
            get {
                return lineHeight;
            }
        }

        public int LineSpace {
            get {
                return this.lineSpace;
            }
            set {
                this.lineSpace = value;
            }
        }

      
        public int CharWidth(char ch, int count) {
            int result;
            if (count == int.MaxValue) {
                result = int.MaxValue;
            } else {
                if (count > 0) {
                    result = count * measureString(ch);
                } else {
                    result = 0;
                }
            }
            return result;
        }
        public int CharWidth(char ch, int width, out int count) {
            int result;
            if (width == int.MaxValue) {
                count = int.MaxValue;
                result = int.MaxValue;
            } else {
                count = 0;
                if (width > 0) {
                    int num = measureString(ch);
                    if (num > 0) {
                        count = width / num;
                        result = count * num;
                        return result;
                    }
                }
                result = 0;
            }
            return result;
        }
        private void FreeBuffer() {
            this.buffer = null;
            this.bufferSize = 0;
        }
   
      
        public int StringWidth(string text, int pos, int len, int width, out int count, bool exact) {
            count = 0;
            int result;
            if (text == null) {
                result = 0;
            } else {
                if (len == -1) {
                    len = text.Length - pos;
                }
                if (width == int.MaxValue) {
                    count = len;
                    result = int.MaxValue;
                } else {
                    {
                        for (int i = pos; i < pos + len; i++) {
                            int num = measureString(text[i]);
                            width -= num;
                            if (width < 0) {
                                if (!exact && width > -num / 2) {
                                    count++;
                                }
                                break;
                            }
                            count++;
                        }
                        result = measureString(text.Substring(pos, count));
                    }
                }
            }
            return result;
        }
 
        protected void SelectOpaque(bool value) {
            if (this._hdc != IntPtr.Zero) {
                Win32.SetBkMode(this._hdc, value ? 2 : 1);
            }
        }
        public void Clear() {
            this.FreeBuffer();
        }
        public void Transform(int x, int y, float scaleX, float scaleY) {
            this.transFormed = true;
            this.oldMode = Win32.SetGraphicsMode(this._hdc, 2);
            this.xForm = new Win32.XFORM(scaleX, 0f, 0f, scaleY, (float)x * scaleX, (float)y * scaleY);
            Win32.SetWorldTransform(this._hdc, ref this.xForm);
        }
        public void EndTransform() {
            if (this.transFormed) {
                this.xForm = new Win32.XFORM(1f, 0f, 0f, 1f, 0f, 0f);
                Win32.SetWorldTransform(this._hdc, ref this.xForm);
                Win32.SetGraphicsMode(this._hdc, this.oldMode);
                this.transFormed = false;
            }
        }
        public void BeginPaint(Graphics graphics) {
            beginPaint(graphics);


            this.graphics = graphics;

        }
        public void EndPaint() {
            this.EndTransform();
            if (this.graphics == null) {
                this.graphics = null;
            }





            endPaint(this.graphics);
        }
        protected Graphics SafeEndPaint() {
            this.safexForm = this.xForm;
            this.safeTransformed = this.transFormed;
            Graphics graphics = this.graphics;
            this.EndPaint();
            if (this.safeTransformed) {
                graphics.Transform = new Matrix(this.safexForm.eM11, this.safexForm.eM12, this.safexForm.eM21, this.safexForm.eM22, this.safexForm.eDx, this.safexForm.eDy);
            }
            return graphics;
        }
        protected void SafeBeginPaint(Graphics gr) {
            if (this.safeTransformed) {
                gr.Transform = new Matrix(1f, 0f, 0f, 1f, 0f, 0f);
            }
            this.BeginPaint(gr);
            if (this.safeTransformed) {
                this.xForm = this.safexForm;
                Win32.SetWorldTransform(this._hdc, ref this.xForm);
                this.transFormed = true;
            }
        }
        protected int[] GetBuffer(int len, int space) {
            int[] result;
            if (space >= 0) {
                if (this.bufferSize < len || (space >= 0 && this.bufferSize > 0 && this.buffer[0] != space)) {
                    this.FreeBuffer();
                    this.bufferSize = len;
                    this.buffer = new int[this.bufferSize];
                    for (int i = 0; i < this.bufferSize; i++) {
                        this.buffer[i] = ((space >= 0) ? space : this.FontWidth);
                    }
                }
                result = this.buffer;
            } else {
                result = null;
            }
            return result;
        }
     
        public int StringWidth(string text, int pos, int len) {
            return measureString(len < 0 ? text : text.Substring(pos, len));
        }
     
        public void FillRectangle(Rectangle rect) {
            this.FillRectangle(rect.Left, rect.Top, rect.Width, rect.Height);
        }
        public void FillRectangle(int x, int y, int width, int height) {
            fillRectangle(x, y,x + width, y+ height);
        }
        public void FillRectangle(Color color, Rectangle rect) {
            BackColor = color;
            this.FillRectangle(rect);
        }

        public void FillGradient(Rectangle rect, Color beginColor, Color endColor, Point point1, Point point2) {
            this.FillGradient(rect.Left, rect.Top, rect.Width, rect.Height, beginColor, endColor, point1, point2);
        }
        public void FillGradient(int x, int y, int width, int height, Color beginColor, Color endColor, Point point1, Point point2) {
            Graphics graphics = this.SafeEndPaint();
            try {
                Brush brush = new LinearGradientBrush(point1, point2, beginColor, endColor);
                graphics.FillRectangle(brush, x, y, width, height);
                brush.Dispose();
            } finally {
                this.SafeBeginPaint(graphics);
            }
        }
        public void DrawThemeBackground(IntPtr handle, int partID, int stateID, Rectangle rect) {
            Win32.GdiRect gdiRect = new Win32.GdiRect(rect);
            Win32.DrawThemeBackground(handle, this._hdc, partID, stateID, ref gdiRect, IntPtr.Zero);
        }
        public void DrawRectangle(Rectangle rect) {
            this.DrawRectangle(rect.Left, rect.Top, rect.Width, rect.Height);
        }
        public void DrawRectangle(int x, int y, int width, int height) {
            drawRectangle(x, y, x + width, y + height);
        }
        public void DrawRoundRectangle(int left, int top, int right, int bottom, int width, int height) {
            drawRoundRectangle(left, top, right, bottom, width, height);
        }
      
        public void DrawFocusRect(int x, int y, int width, int height, Color color) {
            this.DrawDotLine(x, y, x + width, y, color, Color.Empty);
            this.DrawDotLine(x, y, x, y + height, color, Color.Empty);
            this.DrawDotLine(x + width, y, x + width, y + height, color, Color.Empty);
            this.DrawDotLine(x, y + height, x + width, y + height, color, Color.Empty);
        }
        public void DrawImage(ImageList images, int index, Rectangle rect) {
            if (images != null) {
                uint num = 4294967295u;
                Win32.ImageList_DrawEx(images.Handle, index, this._hdc, rect.Left, rect.Top, rect.Width, rect.Height, (int)num, (int)num, 1);
            }
        }
  
        public void DrawLine(int x1, int y1, int x2, int y2) {
            Win32.MoveToEx(this._hdc, x1, y1, IntPtr.Zero);
            Win32.LineTo(this._hdc, x2, y2);
        }

        public void DrawLine(int x1, int y1, int x2, int y2, Color color, int width, DashStyle penStyle) {
            ForeColor = color;
            drawLine(x1, y1, x2, y2, penStyle);
        }

        public void DrawDotLine(int x1, int y1, int x2, int y2, Color color1, Color color2) {
            ForeColor = color1;
            drawDotLine(x1, y1, x2, y2);
        }

        public void DrawEdge(ref Rectangle rect, Border3DStyle border, Border3DSide sides ) {
            Win32.DrawEdge(this._hdc, ref rect, border, sides);
        }
        public void TextOut(string text, int len, int x, int y) {
            this.TextOut(text, len, new Rectangle(x, y, 0, 0), x, y, false, false, -1);
        }
      
        public void TextOut(string text, int len, Rectangle rect, bool clipped, bool opaque) {
            this.TextOut(text, len, rect, rect.Left, rect.Top, clipped, opaque, -1);
        }
      
        public void TextOut(string text, int len, Rectangle rect, int x, int y, bool clipped, bool opaque) {
            this.TextOut(text, len, rect, x, y, clipped, opaque, -1);
        }
        public void TextOut(string text, int len, Rectangle rect, int x, int y, bool clipped, bool opaque, int space) {
            if (text != null) {
                Win32.ExtTextOut(this._hdc, rect, x, y, (clipped ? 4 : 0) | (opaque ? 2 : 0), text, len, (space > 0) ? this.GetBuffer((len < 0) ? text.Length : 0, space) : null);
            }
        }
     
        public void IntersectClipRect(int x, int y, int width, int height) {
            Win32.IntersectClipRect(this._hdc, x, y, x + width, y + height);
        }
        public void ExcludeClipRect(int x, int y, int width, int height) {
            Win32.ExcludeClipRect(this._hdc, x, y, x + width, y + height);
        }

        public void ExcludeClipRect(Rectangle rect) {
            this.ExcludeClipRect(rect.Left, rect.Top, rect.Width, rect.Height);
        }
        public IntPtr SaveClip(Rectangle rect) {
            IntPtr intPtr = Win32.CreateRectRgnIndirect(rect);
            Win32.GetClipRgn(this._hdc, intPtr);
            return intPtr;
        }
        public void RestoreClip(IntPtr rgn) {
            Win32.SelectClipRgn(this._hdc, rgn);
            Win32.DeleteObject(rgn);
        }



        public void DrawWave(Rectangle rect, Color color) {
            ForeColor = color;
            drawWave(rect.X, rect.Right, rect.Y);
        }
        public void DrawPolygon(Point[] points, Color color) {
            ForeColor = color;
            drawPolygon(points);
        }
      
    }
}
